import * as anchor from "@coral-xyz/anchor";
// 引入anchor库，提供Solana合约交互能力。

import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import * as fs from "fs";
import BN from "bn.js";

// 新增：导入代理相关的库
import { SocksProxyAgent } from 'socks-proxy-agent'; // 需要安装 socks-proxy-agent
import fetch from 'node-fetch'; // 只导入 fetch 函数

// 1. 设置代理和RPC
const SOCKS_PROXY_URL = 'socks5://127.0.0.1:10808'; // 你的SOCKS5代理地址
// 如果代理需要认证，格式为: socks5://用户名:密码@127.0.0.1:10808
const socksAgent = new SocksProxyAgent(SOCKS_PROXY_URL);

// 2. 设置RPC与钱包，创建自定义的fetch函数
const RPC_URL = "https://api.devnet.solana.com";

// 创建一个使用代理的自定义fetch实现
const customFetch = async (input: RequestInfo | URL, init?: RequestInit) => {
  // 使用我们配置了代理的socksAgent进行请求
  return fetch(input, {
    ...init
    // ,
    // agent: socksAgent, // 对所有请求使用SOCKS代理
  });
};

// 在创建Connection时传入自定义的fetch函数，调整确认策略
const connection = new Connection(RPC_URL, {
  commitment: "processed", // 使用更快的确认级别
  confirmTransactionInitialTimeout: 10000, // 增加初始超时到60秒
  fetch: customFetch, // 使用自定义的fetch函数，它通过了代理
});

// 3. 读取本地cli钱包（或提前生成的新钱包）
const secretKey = JSON.parse(fs.readFileSync("/Users/guzhongxi/.config/solana/id.json", "utf8"));
const walletKeypair = Keypair.fromSecretKey(new Uint8Array(secretKey));
const wallet = new anchor.Wallet(walletKeypair);

// 4. 设置Provider，使用更宽松的确认设置
const provider = new anchor.AnchorProvider(connection, wallet, { 
  preflightCommitment: "processed",
  commitment: "processed",
  skipPreflight: false, // 确保预检查
});
anchor.setProvider(provider);

// 5. 加载IDL和ProgramID
const idl = JSON.parse(fs.readFileSync("./solana_calculator.json", "utf8")); // 路径如有不同需修改
const programId = new PublicKey("74xT2dYux7UKZMCXQ8xUmbcKUebFrEReS5eMed9rrV1D"); // 智能合约的 ID
const program = new anchor.Program(idl, programId, provider);

// 6. 注意：根据新的IDL，计算器指令不需要账户参数

// 使用手动确认策略，避免依赖自动确认
async function executeWithManualConfirmation(operation: () => Promise<string>, operationName: string): Promise<string> {
  console.log(`开始执行: ${operationName}`);
  
  try {
    // 发送交易但不等待确认
    const signature = await operation();
    console.log(`交易已提交: ${signature}`);
    console.log(`交易链接: https://explorer.solana.com/tx/${signature}?cluster=devnet`);
    
    // 手动检查交易状态
    console.log("正在手动确认交易状态...");
    const confirmation = await connection.confirmTransaction(signature, "processed");
    
    if (confirmation.value.err) {
      throw new Error(`交易失败: ${JSON.stringify(confirmation.value.err)}`);
    }
    
    console.log(`${operationName} 成功确认!`);
    return signature;
    
  } catch (error: any) {
    console.error(`${operationName} 执行失败:`, error.message);
    throw error;
  }
}

async function main() {
  console.log("开始通过代理执行智能合约操作...");
  console.log("使用手动确认策略来避免超时问题...");

  try {
    let a = 55, b = 13;
    
    // 使用手动确认策略执行加法运算
    await executeWithManualConfirmation(
      () => program.methods.add(new BN(a), new BN(b)).rpc(),
      `执行加法运算: ${a} + ${b}`
    );
    
    console.log("所有计算操作已完成！");
    
  } catch (error: any) {
    console.error("操作最终失败: ", error);
    
    // 提供更详细的错误提示
    if (error?.message && typeof error.message === 'string') {
      if (error.message.includes("fetch")) {
        console.log("🔧 建议: 请检查代理服务器是否运行正常，以及代理地址和端口是否正确。");
      } else if (error.message.includes("timeout") || error.message.includes("expired")) {
        console.log("⏰ 建议: 网络连接可能较慢，可以尝试:");
        console.log("   1. 检查网络连接");
        console.log("   2. 稍后重试");
        console.log("   3. 使用更稳定的RPC端点");
      } else if (error.message.includes("insufficient")) {
        console.log("💰 建议: 钱包余额可能不足，请检查SOL余额");
      }
    }
    
    // 如果有交易签名，提供查询链接
    if (error.signature) {
      console.log(`🔍 可以通过以下链接查询交易状态:`);
      console.log(`   https://explorer.solana.com/tx/${error.signature}?cluster=devnet`);
    }
  }
}

main().catch(console.error);